﻿#region Imports
using System.Collections.Generic;
using System.IO;
using CommonUtilities.Enums;
using CommonUtilities.Extensions;
using CommonUtilities.Util;
#endregion

namespace BulkRenamer.Util
{
    /// <summary>
    /// Allows read/write of music tags (ID3)
    /// </summary>
    /// <example>Implementation:
    /// <para>   MusicID3Tag tag = MusicID3Tag.ReadFile(@"C:\Documents and Settings\rhythm divine\My Documents\visual studio 2010\Projects\BulkRenamer\Allah-Ke-Banday-2010-128Kbps(Songs.PK)\Kaala Jaadu.mp3");</para>
    /// <para>   tag.Year = "";</para></example>
    /// <seealso cref="http://social.msdn.microsoft.com/Forums/vstudio/en-US/5c130e39-b42f-4384-83f0-f6282916b9c3/readingwriting-music-files" />
    /// <seealso cref="http://www.codeproject.com/Articles/13328/Reading-ID3-tags-from-a-WMA-file-MP3-as-well" />
    public class MusicID3Tag
    {
        #region Properties
        protected byte[] tagId = new byte[3];
        /// <summary>
        /// Tag Id (length: 3 bytes)
        /// </summary>
        public string TAGID
        {
            get { return Utilities.ConvertByteArrayToString(tagId, true); }
            set { tagId = Utilities.ConvertStringToByteArray(value, tagId.Length); }
        }

        protected byte[] title = new byte[30];
        /// <summary>
        /// Song title (length: 30 bytes)
        /// </summary>
        public string Title
        {
            get { return Utilities.ConvertByteArrayToString(title, true); }
            set { title = Utilities.ConvertStringToByteArray(value, title.Length); }
        }

        protected byte[] artist = new byte[30];
        /// <summary>
        /// Song artist (length: 30 bytes)
        /// </summary>
        public string Artist
        {
            get { return Utilities.ConvertByteArrayToString(artist, true); }
            set { artist = Utilities.ConvertStringToByteArray(value, artist.Length); }
        }

        protected byte[] album = new byte[30];
        /// <summary>
        /// Song album (length: 30 bytes)
        /// </summary>
        public string Album
        {
            get { return Utilities.ConvertByteArrayToString(album, true); }
            set { album = Utilities.ConvertStringToByteArray(value, album.Length); }
        }

        protected byte[] year = new byte[4];
        /// <summary>
        /// Song year (length: 4 bytes)
        /// </summary>
        public string Year
        {
            get { return Utilities.ConvertByteArrayToString(year, true); }
            set { year = Utilities.ConvertStringToByteArray(value, year.Length); }
        }

        protected byte[] comment = new byte[30];
        /// <summary>
        /// Song comment (length: 30 bytes)
        /// </summary>
        public string Comment
        {
            get { return Utilities.ConvertByteArrayToString(comment, true); }
            set { comment = Utilities.ConvertStringToByteArray(value, comment.Length); }
        }

        protected byte[] genre = new byte[1];
        /// <summary>
        /// Song genre (length: 1 byte)
        /// </summary>
        public string Genre
        {
            get { return Utilities.ConvertByteArrayToString(genre, true); }
            set { genre = Utilities.ConvertStringToByteArray(value, genre.Length); }
        }

        public Dictionary<string, int> PropertyInfo { get; set; }
        #endregion

        #region Constructors
        public MusicID3Tag()
        {
            /*
            PropertyInfo = new Dictionary<string, int>();

            //this.GetType().GetProperties().ToList().ForEach(prop => PropertyInfo.Add(prop.Name, Convert.ToInt32(prop.PropertyType.GetProperty("Length").GetValue(prop, null))));
            PropertyInfo.Add("TAGID", tagId.Length);
            PropertyInfo.Add("Title", title.Length);
            PropertyInfo.Add("Artist", artist.Length);
            PropertyInfo.Add("Album", album.Length);
            PropertyInfo.Add("Year", year.Length);
            PropertyInfo.Add("Comment", comment.Length);
            PropertyInfo.Add("Genre", genre.Length);
            */
        }
        #endregion

        #region Methods
        /// <summary>
        /// Reads tags from file
        /// </summary>
        /// <param name="path">File path</param>
        /// <returns>File tags</returns>
        public static MusicID3Tag ReadFile(string path)
        {
            if (!path.ValidatePath(ePathValidation.File)) return null;

            using (FileStream fs = File.OpenRead(path))
            {
                MusicID3Tag tag = new MusicID3Tag();
                if (fs.Length >= 128)
                {
                    fs.Seek(-128, SeekOrigin.End);

                    fs.Read(tag.tagId, 0, tag.tagId.Length);
                    fs.Read(tag.title, 0, tag.title.Length);
                    fs.Read(tag.artist, 0, tag.artist.Length);
                    fs.Read(tag.album, 0, tag.album.Length);
                    fs.Read(tag.year, 0, tag.year.Length);
                    fs.Read(tag.comment, 0, tag.comment.Length);
                    fs.Read(tag.genre, 0, tag.genre.Length);

                    // test - RKD
                    //string theTAGID = Utilities.ConvertByteArrayToString(tag.tagId);
                    //if (theTAGID.Equals("TAG"))
                    //{
                    //    MessageBox.Show(tag.Title, "Title");
                    //    MessageBox.Show(tag.Artist, "Artist");
                    //    MessageBox.Show(tag.Album, "Album");
                    //    MessageBox.Show(tag.Year, "Year");
                    //    MessageBox.Show(tag.Comment, "Comment");
                    //    MessageBox.Show(tag.Genre, "Genre");
                    //}
                }

                return tag;
            }
        }

        /// <summary>
        /// Updates tags into file
        /// </summary>
        /// <param name="tag">File tags</param>
        /// <param name="path">File path</param>
        public static void WriteFile(MusicID3Tag tag, string path)
        {
            using (FileStream fs = File.OpenRead(path))
            {
                fs.Write(tag.tagId, 0, tag.TAGID.Length);
                fs.Write(tag.title, 0, tag.Title.Length);
                fs.Write(tag.artist, 0, tag.Artist.Length);
                fs.Write(tag.album, 0, tag.Album.Length);
                fs.Write(tag.year, 0, tag.Year.Length);
                fs.Write(tag.comment, 0, tag.Comment.Length);
                fs.Write(tag.genre, 0, tag.Genre.Length);
            }
        }

        public override string ToString()
        {
            return Utilities.ToString(this);
        }
        #endregion
    }
}


// http://id3.org/


// Option-1:
// http://stackoverflow.com/questions/10247216/c-sharp-mp3-id-tags-with-taglib-album-art
//TagLib.File tagFile = TagLib.File.Create(path);
//IPicture newArt = new Picture(tmpImg);
//tagFile.Tag.Pictures = new IPicture[1] { newArt };
//tagFile.Save();
////EDIT
//var file = TagLib.File.Create(filename);
//if (file.Tag.Pictures.Length >= 1)
//{
//    var bin = (byte[])(file.Tag.Pictures[0].Data.Data);
//    PreviewPictureBox.Image = Image.FromStream(new MemoryStream(bin)).GetThumbnailImage(100, 100, null, IntPtr.Zero);
//}

// Option-2:
// http://alvas.net/alvas.audio.aspx
// http://alvas.net/alvas.audio,articles.aspx#id3-tags-for-wave-files
//Mp3Reader

// Option-3:
// http://www.codeproject.com/Articles/7987/Retrieve-detailed-information-of-a-File